package rs.fon.is.music.services;

import java.util.LinkedList;

import rs.fon.is.music.persistence.DataModelManager;
import rs.fon.is.music.util.Constants;

public class Queries {

	QueryExecutor executor = new QueryExecutor();

	public LinkedList<String> getGroups(int limit, int offset,int minFoundingYear, int maxFoundingYear, long minAlbums,
			long maxAlbums, long minTracks, long maxTracks, long interactionCount, LinkedList<String> tags) { 

		String query = "PREFIX schema:<" + Constants.SCHEMA + "> " + 
					   "PREFIX xsd:<" + Constants.XSD + ">" + 
					   "SELECT DISTINCT ?thing " + 
					   "WHERE {" + "?thing a schema:MusicGroup";

		if (minFoundingYear != -1 || maxFoundingYear != -1)
			query += "; schema:foundingDate ?date";
		if (minAlbums != -1 || maxAlbums != -1)
			query += "; schema:albums ?albums";
		if (minTracks != -1 || maxTracks != -1)
			query += "; schema:tracks ?tracks";
		if (interactionCount != -1)
			query += "; schema:interactionCount ?interactionCount";
		if (tags.size()>0)
			query += ". ?albums schema:keywords ?keywords.";
		
		if (interactionCount != -1)
			query += "BIND(xsd:long(SUBSTR(?interactionCount,11)) AS ?count) ";
		if (minFoundingYear != -1)
			query += "FILTER(YEAR(?date) >= " + (minFoundingYear - 1) + ")";
		if (maxFoundingYear != -1)
			query += "FILTER(YEAR(?date) <= " + (maxFoundingYear - 1) + ")";
		if (interactionCount != -1)
			query += "FILTER(?count >= " + interactionCount + ")";
		
		String tagsFilter = "";
		for (String tag : tags) {
			tagsFilter += " || ?keywords = \"" + tag + "\"";
		}
		if (tags.size()>0)
			query += "FILTER(" + tagsFilter.substring(4) + ")";
		
		query += "} ";

		if (maxAlbums != -1 || minAlbums != -1 || maxTracks != -1|| minTracks != -1) {
			query += "GROUP BY ?thing HAVING (";
			if (minAlbums != -1) 
				query += " COUNT(?albums) >=" + minAlbums + " &&";
			if (maxAlbums != -1) 
				query += " COUNT(?albums) <=" + maxAlbums + " &&";
			if (minTracks != -1) 
				query += " COUNT(?tracks) >=" + minTracks + " &&";
			if (maxTracks != -1) 
				query += " COUNT(?tracks) <=" + maxTracks + " &&";
			query = query.substring(0, query.lastIndexOf("&&"));
			query += ")";
		}
		

		if (limit != -1)
			query += " LIMIT " + limit;
		if (offset != -1)
			query += " OFFSET " + offset;

		return (LinkedList<String>) executor.executeOneVariableSelectSparqlQuery(query, "thing", DataModelManager.getInstance().getModel());
	}
	
	public LinkedList<String> getAlbums(String groupID, int limit, int offset, long minTracks, long maxTracks, long interactionCount, LinkedList<String> tags) { 

		String query = "PREFIX schema:<" + Constants.SCHEMA + "> " + 
				   "PREFIX xsd:<" + Constants.XSD + "> " + 
				   "SELECT DISTINCT ?album " + 
				   "WHERE { ?album a schema:MusicAlbum";

		query += "; schema:byArtist <http://is.fon.rs/music/MusicGroup/" + groupID + ">";
		if (minTracks != -1 || maxTracks != -1)
			query += "; schema:numTracks ?numTracks";
		if (tags.size()>0)
			query += "; schema:keywords ?keywords.";
		if (interactionCount != -1){
			query += "; schema:interactionCount ?interactionCount";
			query += "BIND(xsd:long(SUBSTR(?interactionCount,11)) AS ?count) ";
			query += "FILTER(?count >= " + interactionCount + ")";
		}
		
		String tagsFilter = "";
		for (String tag : tags) {
			tagsFilter += " || ?keywords = \"" + tag + "\"";
		}
		if (tags.size()>0)
			query += " FILTER(" + tagsFilter.substring(4) + ")";

		if (maxTracks != -1|| minTracks != -1) {
			query += " FILTER(";
			if (minTracks != -1) 
				query += " ?numTracks >=" + minTracks + " &&";
			if (maxTracks != -1) 
				query += " ?numTracks <=" + maxTracks + " &&";
			query = query.substring(0, query.lastIndexOf("&&"));
			query += ")";
		}
		
		query += "} ";
	
		if (limit != -1)
			query += " LIMIT " + limit;
		if (offset != -1)
			query += " OFFSET " + offset;
	
		return (LinkedList<String>) executor.executeOneVariableSelectSparqlQuery(query, "album", DataModelManager.getInstance().getModel());
	}
	
	public LinkedList<String> getRecordings(String groupID, int limit, int offset, long interactionCount, LinkedList<String> tags) { 

		String query = "PREFIX schema:<" + Constants.SCHEMA + "> " + 
				   "PREFIX xsd:<" + Constants.XSD + "> " + 
				   "SELECT DISTINCT ?recording " + 
				   "WHERE { ?recording a schema:MusicRecording";

		query += "; schema:byArtist <http://is.fon.rs/music/MusicGroup/" + groupID + ">";
		if (tags.size()>0)
			query += "; schema:keywords ?keywords.";
		if (interactionCount != -1){
			query += "; schema:interactionCount ?interactionCount";
			query += "BIND(xsd:long(SUBSTR(?interactionCount,11)) AS ?count) ";
			query += "FILTER(?count >= " + interactionCount + ")";
		}
		
		String tagsFilter = "";
		for (String tag : tags) {
			tagsFilter += " || ?keywords = \"" + tag + "\"";
		}
		if (tags.size()>0)
			query += " FILTER(" + tagsFilter.substring(4) + ")";
		
		query += "} ";
	
		if (limit != -1)
			query += " LIMIT " + limit;
		if (offset != -1)
			query += " OFFSET " + offset;
	
		return (LinkedList<String>) executor.executeOneVariableSelectSparqlQuery(query, "recording", DataModelManager.getInstance().getModel());
	}

	public LinkedList<String> getAlbumRecordings(String albumID, int limit, int offset, long interactionCount, LinkedList<String> tags) {
		
		String query = "PREFIX schema:<" + Constants.SCHEMA + "> " + 
				   "PREFIX xsd:<" + Constants.XSD + "> " + 
				   "SELECT DISTINCT ?recording " + 
				   "WHERE { ?recording a schema:MusicRecording";

		query += "; schema:inAlbum <http://is.fon.rs/music/MusicAlbum/" + albumID + ">";
		if (tags.size()>0)
			query += "; schema:keywords ?keywords.";
		if (interactionCount != -1){
			query += "; schema:interactionCount ?interactionCount";
			query += "BIND(xsd:long(SUBSTR(?interactionCount,11)) AS ?count) ";
			query += "FILTER(?count >= " + interactionCount + ")";
		}
		
		String tagsFilter = "";
		for (String tag : tags) {
			tagsFilter += " || ?keywords = \"" + tag + "\"";
		}
		if (tags.size()>0)
			query += " FILTER(" + tagsFilter.substring(4) + ")";
		
		query += "} ";
	
		if (limit != -1)
			query += " LIMIT " + limit;
		if (offset != -1)
			query += " OFFSET " + offset;
	
		return (LinkedList<String>) executor.executeOneVariableSelectSparqlQuery(query, "recording", DataModelManager.getInstance().getModel());
	}
}

